﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Script.cs" company="Anton Frattaroli">
//   Copyright (c) Anton Frattaroli. All rights reserved.
// </copyright>
// <summary>
//   Defines the Script class.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace Lidocaine
{
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.SqlClient;
    using System.Globalization;

    /// <summary>
    /// Defines the Script class.
    /// </summary>
    public class Script
    {
        #region Fields
        /// <summary>
        /// The identity of the database table's row where this script object is saved.
        /// </summary>
        private int scriptID;

        /// <summary>
        /// Stores the script type for this script (CSS or JS).
        /// </summary>
        private ScriptType scriptType;

        /// <summary>
        /// Stores the script's given name.
        /// </summary>
        private string scriptName;

        /// <summary>
        /// Stores the script's actual content.
        /// </summary>
        private string scriptText;
        #endregion

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the Script class.
        /// </summary>
        public Script()
        {
        }

        /// <summary>
        /// Initializes a new instance of the Script class.
        /// </summary>
        /// <param name="scriptId">The identity of the database table's row referencing this script.</param>
        public Script(int scriptId)
        {
            using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
            {
                conn.Open();
                using (SqlCommand cmd = new SqlCommand("Lidocaine.GetScriptInfo", conn))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddWithValue("@ID", scriptId);
                    using (SqlDataReader rdr = cmd.ExecuteReader())
                    {
                        if (rdr.HasRows)
                        {
                            rdr.Read();
                            this.scriptID = Convert.ToInt32(rdr["ScriptID"], CultureInfo.InvariantCulture);
                            this.scriptType = rdr["ScriptType"].ToString() == "True" ? ScriptType.Css : ScriptType.JS;
                            this.scriptName = (string)rdr["ScriptName"];
                            this.scriptText = rdr["ScriptText"].ToString();
                        }
                        else
                        {
                            throw new DataException("Script does not exist.");
                        }
                    }
                }
            }
        }
        #endregion

        #region Properties
        /// <summary>
        /// Gets the script's database row identity.
        /// </summary>
        public int ScriptId
        {
            get
            {
                return this.scriptID;
            }
        }

        /// <summary>
        /// Gets or sets the script's given name.
        /// </summary>
        public string ScriptName
        {
            get
            {
                return this.scriptName;
            }

            set
            {
                this.scriptName = value;
            }
        }

        /// <summary>
        /// Gets or sets the script's content.
        /// </summary>
        public string ScriptText
        {
            get
            {
                return this.scriptText;
            }

            set
            {
                this.scriptText = value;
            }
        }

        /// <summary>
        /// Gets or sets the script's type.
        /// </summary>
        public ScriptType ScriptType
        {
            get
            {
                return this.scriptType;
            }

            set
            {
                this.scriptType = value;
            }
        }
        #endregion

        #region Methods
        /// <summary>
        /// Gets a dictionary of scripts for the current application (determined by the connection's sql user account.)
        /// </summary>
        /// <param name="scriptType">The type of scripts to return (CSS or JS).</param>
        /// <returns>A dictionary object containing row identity keys and the referenced script's given name.</returns>
        public static Dictionary<int, string> GetScripts(ScriptType scriptType)
        {
            Dictionary<int, string> scripts = new Dictionary<int, string>();
            using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
            {
                conn.Open();
                using (SqlCommand cmd = new SqlCommand("Lidocaine.GetScripts", conn))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddWithValue("@ScriptType", scriptType == ScriptType.Css ? 1 : 0);
                    using (SqlDataReader rdr = cmd.ExecuteReader())
                    {
                        if (rdr.HasRows)
                        {
                            while (rdr.Read())
                            {
                                scripts.Add(Convert.ToInt32(rdr["ScriptID"], CultureInfo.InvariantCulture), (string)rdr["scriptName"]);
                            }
                        }
                    }
                }
            }

            return scripts;
        }

        /// <summary>
        /// Inserts the HScript object into the database.
        /// </summary>
        public void SaveAs()
        {
            using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
            {
                conn.Open();
                using (SqlCommand cmd = new SqlCommand("Lidocaine.InsertScript", conn))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddWithValue("@ScriptType", this.scriptType == ScriptType.Css ? 1 : 0);
                    cmd.Parameters.AddWithValue("@ScriptName", this.scriptName);
                    this.scriptID = Convert.ToInt32(cmd.ExecuteScalar(), CultureInfo.InvariantCulture);
                }
            }
        }

        /// <summary>
        /// Updates the HScript's database fields.
        /// </summary>
        public void Save()
        {
            using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
            {
                conn.Open();
                using (SqlCommand cmd = new SqlCommand("Lidocaine.UpdateScript", conn))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddWithValue("@ScriptID", this.scriptID);
                    cmd.Parameters.AddWithValue("@ScriptName", this.scriptName);
                    cmd.Parameters.AddWithValue("@ScriptText", this.scriptText);
                    cmd.ExecuteNonQuery();
                }
            }
        }

        /// <summary>
        /// Gets the titles of pages related to this script.
        /// </summary>
        /// <returns>A readonly list of the titles of the pages referencing this script.</returns>
        public IList<string> GetPages()
        {
            List<string> pages = new List<string>();
            using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
            {
                conn.Open();
                if (this.scriptType == ScriptType.Css)
                {
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.GetCSSPages", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@ID", this.scriptID);
                        using (SqlDataReader rdr = cmd.ExecuteReader())
                        {
                            if (rdr.HasRows)
                            {
                                while (rdr.Read())
                                {
                                    if (rdr["Name"] == DBNull.Value)
                                    {
                                        pages.Add(string.Empty);
                                    }
                                    else
                                    {
                                        pages.Add((string)rdr["Name"]);
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.GetJSPages", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@ID", this.scriptID);
                        using (SqlDataReader rdr = cmd.ExecuteReader())
                        {
                            if (rdr.HasRows)
                            {
                                while (rdr.Read())
                                {
                                    if (rdr["Name"] == DBNull.Value)
                                    {
                                        pages.Add(string.Empty);
                                    }
                                    else
                                    {
                                        pages.Add((string)rdr["Name"]);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return pages.AsReadOnly();
        }

        /// <summary>
        /// Deletes the HScript's database entry and nullifies and page references to this script.
        /// </summary>
        public void Delete()
        {
            using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
            {
                conn.Open();
                if (this.scriptType == ScriptType.Css)
                {
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.DeleteCSS", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@ID", this.scriptID);
                        cmd.ExecuteNonQuery();
                    }
                }
                else if (this.scriptType == ScriptType.JS)
                {
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.DeleteJS", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@ID", this.scriptID);
                        cmd.ExecuteNonQuery();
                    }
                }
            }
        }
        #endregion
    }
}